#ifndef CNOTEDISPLAYWIDGET_H
#define CNOTEDISPLAYWIDGET_H

#include <MWidget>
#include <QGraphicsWebView>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <QAbstractAnimation>
#include <QWebFrame>
#include "QvernoteAPI.h"
#include "QEnmlReader.h"
#include "QClickableGraphicsWebView.h"
#include <MDebug>
#include <MLabel>

class CNoteWidgetAnimation : public QAbstractAnimation
{
    Q_OBJECT

public:
    CNoteWidgetAnimation(int duration = 10000) : m_duration(duration) {
        setLoopCount(-1);
    }

    int duration() const {
        return m_duration;
    }

    void updateCurrentTime(int currentTime) {
        emit frameAdvance(currentTime);
    }

signals:
    void frameAdvance(int);

private:
    int m_duration;
};

class CNoteLoadingAnimationWidget : public MWidget
{
    Q_OBJECT

public:
    CNoteLoadingAnimationWidget(Note& note, QGraphicsItem* parent = 0)
        : m_Note(note), MWidget(parent) {
        currentProgress = 0;
        noteLoadingAnimation = new CNoteWidgetAnimation(10000);
        MLayout* layout = new MLayout(this);
        mainLayoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);

        noteHtmlView.page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);

        QObject::connect(noteLoadingAnimation, SIGNAL(frameAdvance(int)), this, SLOT(updateLoadingProgress(int)));
        QObject::connect(noteLoadingAnimation, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), this, SLOT(startLoadHtml(QAbstractAnimation::State,QAbstractAnimation::State)));
        QObject::connect(&noteHtmlView, SIGNAL(loadFinished(bool)), this, SLOT(onHtmlLoadFinished(bool)), Qt::QueuedConnection);
    }

    ~CNoteLoadingAnimationWidget() {
        qDebug() << "Destroy anim widget";
        noteLoadingAnimation->stop();
        delete noteLoadingAnimation;
    }

    void run() {
        noteLoadingAnimation->start();
    }

    void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {
        painter->drawText(boundingRect(), Qt::AlignCenter, QString("Progress: %1").arg(currentProgress));
        //painter->drawPixmap(boundingRect().width()/2, boundingRect().height() / 2, QPixmap(":/IconAdd/loading45.gif"));
        MWidget::paint(painter, option, widget);
    }

    QClickableGraphicsWebView* getNoteRenderer() {
        return &noteHtmlView;
    }

    Note& getNote() {
        return m_Note;
    }

    QEnmlReader* getNoteParser() {
        return &enmlReader;
    }

    static void runHtmlRendering(CNoteLoadingAnimationWidget* obj) {
        obj->getNoteParser()->parse(obj->getNote());
        obj->getNoteRenderer()->setHtml(obj->getNoteParser()->getHtml());
    }


public slots:
    void updateLoadingProgress(int progress) {
        currentProgress = progress;
        update();
    }

    void startLoadHtml(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) {
        if(newState == QAbstractAnimation::Running && oldState == QAbstractAnimation::Stopped) {
            //QFuture<void> future = QtConcurrent::run(runHtmlRendering, this);
            mDebug("CNoteLoadingAnimationWidget") << "Running the render";
            enmlReader.parse(m_Note);
            noteHtmlView.setHtml(enmlReader.getHtml());

            //future.waitForFinished();
        }
    }

    void onHtmlLoadFinished(bool) {
        noteLoadingAnimation->stop();
         mDebug("CNoteLoadingAnimationWidget") << "Render finished";
        emit triggerHtmlLoadFinished();
    }

signals:
    void triggerHtmlLoadFinished();

private:
    CNoteWidgetAnimation*  noteLoadingAnimation;
    MLinearLayoutPolicy*    mainLayoutPolicy;
    QClickableGraphicsWebView        noteHtmlView;
    QEnmlReader             enmlReader;
    int                     currentProgress;
    Note                    m_Note;
};

class CNoteDisplayWidget : public MWidget
{
    Q_OBJECT

public:
    CNoteDisplayWidget(const Note& note, QGraphicsItem* parent = 0)
        : m_Note(note), MWidget(parent) {

        MLayout* layout = new MLayout(this);
        mainLayoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
        noteLoadingWidget = new CNoteLoadingAnimationWidget(m_Note);
        mainLayoutPolicy->addItem(new MLabel());
        mainLayoutPolicy->addItem(noteLoadingWidget);

        QObject::connect(noteLoadingWidget, SIGNAL(triggerHtmlLoadFinished()), this, SLOT(onHtmlLoadFinished()));

    }

    ~CNoteDisplayWidget() {
        qDebug() << "Destroy note widget";
        delete noteLoadingWidget;
    }

    void render() {
        noteLoadingWidget->run();
    }

    QClickableGraphicsWebView* GetRenderer() {
        return noteLoadingWidget->getNoteRenderer();
    }

    QSize contentSize() {
        return noteLoadingWidget->getNoteRenderer()->page()->mainFrame()->contentsSize();
    }


public slots:
    void onHtmlLoadFinished() {
        qDebug() << "Replacing widgets";
        QClickableGraphicsWebView* noteHtmlView = noteLoadingWidget->getNoteRenderer();
        mainLayoutPolicy->removeItem(noteLoadingWidget);
        qDebug() << "Resizing to " << noteHtmlView->page()->mainFrame()->contentsSize();

        QSize s = noteHtmlView->page()->mainFrame()->contentsSize();
        const QRectF fr = noteHtmlView->geometry();
        const QRectF cr = noteHtmlView->contentsRect();

        //qDebug() << trUtf8("contentSize") << s;
        //qDebug() << trUtf8("frameGeometry") << fr;
        //qDebug() << trUtf8("contentRect") << cr;
        //s.setHeight(s.height() + 1 * ui.wvNoteEdit->fontMetrics().lineSpacing());

        noteHtmlView->setMinimumHeight(qMax(70, (int)(s.height()  + (fr.height() - cr.height() - 1) + 20)));
        noteHtmlView->setMinimumWidth(qMax((int)geometry().width() /*- 16*/, s.width()));
        //emit widgetReady(this);
        //noteHtmlView->setTransformOriginPoint(QPointF(geometry().width() / 2, geometry().height() / 2));

        //resize(noteLoadingWidget->getNoteRenderer()->page()->mainFrame()->contentsSize());
        if(noteHtmlView->page()->mainFrame()->contentsSize().width() > parentWidget()->boundingRect().width())
        {
            qDebug() << "Scale to: " << parentWidget()->boundingRect().width() << (qreal)contentSize().width() << parentWidget()->boundingRect().width() / (qreal)contentSize().width();
            //noteHtmlView->setZoomFactor(parentWidget()->boundingRect().width() / (qreal)contentSize().width());
        }

        QObject::connect(noteHtmlView, SIGNAL(scaleUpdate(qreal)), this, SLOT(onScaleUpdate(qreal)));
        mainLayoutPolicy->addItem(noteHtmlView);
        //noteHtmlView->setScale(parentWidget()->boundingRect().width() / contentSize().width());
    }

    void onScaleUpdate(qreal scale) {
        qDebug() << "Scale updated" << scale;
        noteLoadingWidget->getNoteRenderer()->setZoomFactor(scale);
    }

signals:
    void widgetReady(CNoteDisplayWidget*);

private:
    Note m_Note;
    MLinearLayoutPolicy*    mainLayoutPolicy;
    CNoteLoadingAnimationWidget* noteLoadingWidget;
    //bool                    renderComplete;
    //bool                    hasParent;
    //QMutex                  renderLock;
};

#endif // CNOTEDISPLAYWIDGET_H
